import * as THREE from 'three';

class SketchCoordinateSystem {
  #tempMatrix = new THREE.Matrix4(); // 坐标系切换X Y Z轴时，根据该矩阵进行切换
  #curMatrix = new THREE.Matrix4(); // 坐标系发生任何变化时，需要更新该矩阵
  #curNormal = 'Z';
  #plane = new THREE.Plane(new THREE.Vector3( 0, 0, 1 ));
  #norm = new THREE.Vector3();
  #position = new THREE.Vector3();
  #scale = 1; // x, y, z的缩放比例需保持相同

  getMatrix() {
    return this.#curMatrix
  }
  
  getScale() {
    return this.#scale;
  }

  getNorm() {
    return this.#norm;
  }

  // 坐标系原点
  getPosition() {
    return this.#position;
  }

  getPlane() {
    return this.#plane;
  }

  // 构建草图坐标系
  setMatrix(matrix = new THREE.Matrix4()) {
    this.#curNormal = 'Z';
    this.#setTempMatrix(matrix);
    this.#setCurMatrix(matrix);
    this.#scale = new THREE.Vector3().setFromMatrixColumn(matrix, 0).length();
  }

  dispose() {
    let matrix = new THREE.Matrix4();
    this.#curNormal = 'Z';
    this.#setTempMatrix(matrix);
    this.#setCurMatrix(matrix);
    this.#scale = 1;
  }

  // 保持坐标系原点不变，在X Y Z轴中切换法向
  switchNormal() {
    let position = new THREE.Vector3().setFromMatrixPosition(this.#tempMatrix);
    let xAxis = new THREE.Vector3();
    let yAxis = new THREE.Vector3();
    let zAxis = new THREE.Vector3();
    this.#tempMatrix.extractBasis(xAxis, yAxis, zAxis);
    let matrix = new THREE.Matrix4();
    if (this.#curNormal === 'Z') {
      this.#curNormal = 'X';
      matrix.makeBasis(yAxis, zAxis, xAxis);
    } else if (this.#curNormal === 'X') {
      this.#curNormal = 'Y';
      matrix.makeBasis(zAxis, xAxis, yAxis);
    } else if (this.#curNormal === 'Y') {
      this.#curNormal = 'Z';
      matrix.makeBasis(xAxis, yAxis, zAxis);
    }
    matrix.setPosition(position);
    this.#setCurMatrix(matrix);
  }

  //切换法向至目标方向
  switchNormalToTarget(target) {
    let position = new THREE.Vector3().setFromMatrixPosition(this.#tempMatrix);
    let xAxis = new THREE.Vector3();
    let yAxis = new THREE.Vector3();
    let zAxis = new THREE.Vector3();
    this.#tempMatrix.extractBasis(xAxis, yAxis, zAxis);
    let matrix = new THREE.Matrix4();
    if (target === 'Z' && this.#curNormal !== 'Z') {
      this.#curNormal = 'Z';
      matrix.makeBasis(xAxis, yAxis, zAxis);
    } else if (target === 'Y' && this.#curNormal !== 'Y') {
      this.#curNormal = 'Y';
      matrix.makeBasis(zAxis, xAxis, yAxis);
    } else if (target === 'X' && this.#curNormal !== 'X') {
      this.#curNormal = 'X';
      matrix.makeBasis(yAxis, zAxis, xAxis);
    } else {
      return
    }
    matrix.setPosition(position);
    this.#setCurMatrix(matrix);
  }

  setPosition(position) {
    let matrix = this.#tempMatrix.clone();
    matrix.setPosition(position);
    this.#setTempMatrix(matrix);
    matrix = this.#curMatrix.clone();
    matrix.setPosition(position);
    this.#setCurMatrix(matrix);
  }

  #setTempMatrix(matrix) {
    this.#tempMatrix.copy(matrix);
  }

  #setCurMatrix(matrix) {
    this.#curMatrix.copy(matrix);
    this.#plane.set(new THREE.Vector3(0, 0, 1), 0);
    this.#plane.applyMatrix4(matrix);
    this.#norm.setFromMatrixColumn(matrix, 2).normalize();
    this.#position.setFromMatrixPosition(matrix);
  }
}

const sketchCoordinateSystem = new SketchCoordinateSystem();
export { sketchCoordinateSystem }